home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / TURBOPASCAL WIN / RWDEMOS.PAK / BITBTN.PAS < prev    next >
Pascal/Delphi Source File  |  1992-06-08  |  22KB  |  723 lines

  1. {************************************************}
  2. {                                                }
  3. {   Turbo Pascal for Windows                     }
  4. {   Demo library (DLL)                           }
  5. {   Copyright (c) 1992 by Borland International  }
  6. {                                                }
  7. {************************************************}
  8.  
  9. library BitBtn;
  10.  
  11. uses WinTypes, WinProcs, Strings, CustCntl, BitBtnCo;
  12.  
  13. {$R BITBTN.RES}
  14.  
  15. { ==============================================================
  16.   Bitmaped button custom control.
  17.   ============================================================== }
  18.  
  19. const
  20.   ofReserved    = 0;  { Used by the dialog manager }
  21.   ofState       = 2;
  22.   ofDownBits    = 4;
  23.   ofUpBits      = 6;
  24.   ofFocUpBits   = 8;
  25.   ofSize        = 10; { Amount of window extra bytes to use }
  26.  
  27. const
  28.   bdBorderWidth = 1;
  29.  
  30. const
  31.   bsDisabled    = $0001;
  32.   bsFocus       = $0002;
  33.   bsKeyDown     = $0004;
  34.   bsMouseDown   = $0008;
  35.   bsMouseUpDown = $0010;
  36.   bsDefault     = $0020;
  37.  
  38. { GetAppInstance -----------------------------------------------
  39.     Returns a handle to the current client application.
  40.   -------------------------------------------------------------- }
  41. function GetAppInstance: THandle; near; assembler;
  42. asm
  43.     PUSH    SS
  44.     CALL    GlobalHandle
  45. end;
  46.  
  47. { IsWorkshopWindow ---------------------------------------------
  48.     Returns true if the window belongs to Resource Workshop.
  49.     Used to determine if the control is being edited; allowing
  50.     the LoadResRW function to be called.
  51.   -------------------------------------------------------------- }
  52. function IsWorkshopWindow(Wnd: HWnd): Boolean;
  53. var
  54.   Parent: HWnd;
  55.   ClassName: array[0..80] of Char;
  56. begin
  57.   Parent := Wnd;
  58.   repeat
  59.     Wnd := Parent;
  60.     Parent := GetParent(Wnd);
  61.   until Parent = 0;
  62.   GetClassName(Wnd, ClassName, SizeOf(ClassName));
  63.   IsWorkshopWindow := StrComp(ClassName, 'rwswnd') = 0;
  64. end;
  65.  
  66. { LoadResRW ----------------------------------------------------
  67.     Load a resource from Resource Workshop. Initialized by
  68.     ListClasses below.
  69.   -------------------------------------------------------------- }
  70. var
  71.   LoadResRW: TLoad;
  72.  
  73. { LoadBitmapRW -------------------------------------------------
  74.     Load a bitmap from Resource Workshop.  *MUST* be called from
  75.     inside resource workshop (IsWorkshopWindow must be true).
  76.   -------------------------------------------------------------- }
  77. function LoadBitmapRW(szTitle: PChar): HBitmap;
  78. var
  79.   Res: THandle;
  80.   Bits: PBitMapInfoHeader;
  81.   DC: HDC;
  82.   nColors: Integer;
  83.   Ret: HBitmap;
  84.  
  85. function GetDInColors(BitCount: Integer): Integer;
  86. begin
  87.   case BitCount of
  88.     1, 3, 4, 8: GetDInColors := 1 shl BitCount;
  89.   else
  90.     GetDInColors := 0;
  91.   end;
  92. end;
  93.  
  94. begin
  95.   LoadBitmapRW := 0;
  96.   Res := LoadResRW(rt_Bitmap, szTitle);
  97.   if Res <> 0 then
  98.   begin
  99.     Bits := GlobalLock(Res);
  100.     if Bits^.biSize = SizeOf(TBitMapInfoHeader) then
  101.     begin
  102.       nColors := GetDInColors(Bits^.biBitCount);
  103.       DC := GetDC(0);
  104.       if DC <> 0 then
  105.       begin
  106.     LoadBitmapRW := CreateDIBitmap(DC, Bits^, cbm_Init,
  107.       Pointer(LongInt(Bits) + SizeOf(Bits^) +
  108.       nColors * SizeOf(TRGBQuad)), PBitmapInfo(Bits)^,
  109.       dib_RGB_Colors);
  110.     ReleaseDC(0, DC);
  111.       end;
  112.     end;
  113.     GlobalUnlock(Res);
  114.     GlobalFree(Res);
  115.   end;
  116. end;
  117.  
  118. { BitButtonWinFn -----------------------------------------------
  119.     Button window procedure.
  120.   -------------------------------------------------------------- }
  121. function BitButtonWinFn(HWindow: HWnd; Message: Word; wParam: Word;
  122.   lParam: Longint): Longint; export;
  123. var
  124.   DC: HDC;
  125.   BitsNumber: Integer;
  126.   Bitmap: TBitmap;
  127.   Rect: TRect;
  128.   Pt: TPoint;
  129.   PS: TPaintStruct;
  130.  
  131. { Get ----------------------------------------------------------
  132.     Get a window instance word.
  133.   -------------------------------------------------------------- }
  134. function Get(Ofs: Integer): Word;
  135. begin
  136.   Get := GetWindowWord(HWindow, Ofs);
  137. end;
  138.  
  139. { SetWord ------------------------------------------------------
  140.     Set the value of a window instance word.
  141.   -------------------------------------------------------------- }
  142. procedure SetWord(Ofs: Integer; Val: Word);
  143. begin
  144.   SetWindowWord(HWindow, Ofs, Val);
  145. end;
  146.  
  147. { State --------------------------------------------------------
  148.     Get the button's state word.
  149.   -------------------------------------------------------------- }
  150. function State: Word;
  151. begin
  152.   State := Get(ofState);
  153. end;
  154.  
  155. { DownBits -----------------------------------------------------
  156.     Get the "down" bitmap of the button.
  157.   -------------------------------------------------------------- }
  158. function DownBits: Word;
  159. begin
  160.   DownBits := Get(ofDownBits);
  161. end;
  162.  
  163. { UpBits -------------------------------------------------------
  164.     Get the "up" bitmap of the button.
  165.   -------------------------------------------------------------- }
  166. function UpBits: Word;
  167. begin
  168.   UpBits := Get(ofUpBits);
  169. end;
  170.  
  171. { FocUpBits ----------------------------------------------------
  172.     Get the "focused up" bitmap of the button.
  173.   -------------------------------------------------------------- }
  174. function FocUpBits: Word;
  175. begin
  176.   FocUpBits := Get(ofFocUpBits);
  177. end;
  178.  
  179. { GetState -----------------------------------------------------
  180.     Get the value of a state bit.
  181.   -------------------------------------------------------------- }
  182. function GetState(AState: Word): Boolean;
  183. begin
  184.   GetState := (State and AState) = AState;
  185. end;
  186.  
  187. { Paint --------------------------------------------------------
  188.     Paint the button.  Called in responce to a WM_PAINT message
  189.     and whenever the button changes state (called by Repaint).
  190.   -------------------------------------------------------------- }
  191. procedure Paint(DC: HDC);
  192. const
  193.   coGray = $00C0C0C0;
  194. var
  195.   MemDC: HDC;
  196.   Bits, Oldbitmap: HBitmap;
  197.   BorderBrush, OldBrush: HBrush;
  198.   LogBrush: TLogBrush;
  199.   DisableBits: HBitmap;
  200.   Frame: TRect;
  201.   Height, Width: Integer;
  202. begin
  203.   if (State and (bsMouseDown + bsKeyDown) <> 0) and
  204.       not GetState(bsMouseUpDown) then
  205.     Bits := DownBits
  206.   else
  207.     if GetState(bsFocus) then
  208.       Bits := FocUpBits
  209.     else
  210.       Bits := UpBits;
  211.  
  212.   { Draw border }
  213.   GetClientRect(HWindow, Frame);
  214.   Height := Frame.bottom - Frame.top;
  215.   Width := Frame.right - Frame.left;
  216.  
  217.   if GetState(bsDefault) then
  218.     BorderBrush := GetStockObject(Black_Brush)
  219.   else BorderBrush := GetStockObject(White_Brush);
  220.   OldBrush := SelectObject(DC, BorderBrush);
  221.   PatBlt(DC, Frame.left, Frame.top, Width, bdBorderWidth, PatCopy);
  222.   PatBlt(DC, Frame.left, Frame.top, bdBorderWidth, Height, PatCopy);
  223.   PatBlt(DC, Frame.left, Frame.bottom - bdBorderWidth, Width,
  224.     bdBorderWidth, PatCopy);
  225.   PatBlt(DC, Frame.right - bdBorderWidth, Frame.top, bdBorderWidth,
  226.     Height, PatCopy);
  227.   SelectObject(DC, OldBrush);
  228.  
  229.   { Draw bitmap }
  230.   MemDC := CreateCompatibleDC(DC);
  231.   OldBitmap := SelectObject(MemDC, Bits);
  232.   GetObject(Bits, Sizeof(Bitmap), @Bitmap);
  233.   if GetState(bsDisabled) then
  234.   begin
  235.     { Gray out the button }
  236.     OldBrush := SelectObject(DC, CreateSolidBrush(coGray));
  237.     PatBlt(DC, bdBorderWidth, bdBorderWidth, Bitmap.bmWidth,
  238.       Bitmap.bmHeight, PatCopy);
  239.     DeleteObject(SelectObject(DC, OldBrush));
  240.  
  241.     { Draw the bitmap through a checked brush }
  242.     LogBrush.lbStyle := bs_Pattern;
  243.     LogBrush.lbHatch := LoadBitmap(HInstance, MakeIntResource(btDisableBits));
  244.     OldBrush := SelectObject(DC, CreateBrushIndirect(LogBrush));
  245.     BitBlt(DC, bdBorderWidth, bdBorderWidth, Bitmap.bmWidth,
  246.       Bitmap.bmHeight, MemDC, 0, 0, $00A803A9 {DPSoa});
  247.     DeleteObject(SelectObject(DC, OldBrush));
  248.     DeleteObject(LogBrush.lbHatch);
  249.   end
  250.   else
  251.     BitBlt(DC, bdBorderWidth, bdBorderWidth, Bitmap.bmWidth,
  252.       Bitmap.bmHeight, MemDC, 0, 0, srcCopy);
  253.   SelectObject(MemDC, OldBitmap);
  254.  
  255.   DeleteDC(MemDC);
  256. end;
  257.  
  258. { Repaint ------------------------------------------------------
  259.     Repaint the button. Called whenever the button changes
  260.     state.
  261.   -------------------------------------------------------------- }
  262. procedure Repaint;
  263. var
  264.   DC: HDC;
  265. begin
  266.   DC := GetDC(HWindow);
  267.   Paint(DC);
  268.   ReleaseDC(HWindow, DC);
  269. end;
  270.  
  271. { SetState -----------------------------------------------------
  272.     Sets the value of a state bit.  If the word changes value
  273.     the button is repainted.
  274.   -------------------------------------------------------------- }
  275. procedure SetState(AState: Word; Enable: Boolean);
  276. var
  277.   OldState, NewState: Word;
  278. begin
  279.   OldState := State;
  280.   if Enable then NewState := OldState or AState
  281.   else NewState := OldState and not AState;
  282.   if NewState <> OldState then
  283.   begin
  284.     SetWord(ofState, NewState);
  285.     Repaint;
  286.   end;
  287. end;
  288.  
  289. { InMe ---------------------------------------------------------
  290.     Returns true if the given point is in within the border of
  291.     the button.
  292.   -------------------------------------------------------------- }
  293. function InMe(lPoint: Longint): Boolean;
  294. var
  295.   R: TRect;
  296.   Point: TPoint absolute lPoint;
  297. begin
  298.   GetClientRect(HWindow, R);
  299.   InflateRect(R, -bdBorderWidth, -bdBorderWidth);
  300.   InMe := PtInRect(R, Point);
  301. end;
  302.  
  303. { ButtonPressed ------------------------------------------------
  304.     Called when the button is pressed by either the keyboard or
  305.     by the mouse.
  306.   -------------------------------------------------------------- }
  307. procedure ButtonPressed;
  308. begin
  309.   SetState(bsMouseDown + bsMouseUpDown + bsKeyDown, False);
  310.   SendMessage(GetParent(HWindow), wm_Command, GetDlgCtrlID(HWindow),
  311.     Longint(HWindow));
  312. end;
  313.  
  314. { LoadBits -----------------------------------------------------
  315.     Load the bitmap for the button or the "NO BITMAP" version
  316.     if it does not exist.
  317.   -------------------------------------------------------------- }
  318. procedure LoadBits(Wrd: Word; MapNumber: Word);
  319. var
  320.   MapBits: HBitmap;
  321. begin
  322.   MapBits := LoadBitmap(HInstance, pChar(MapNumber));
  323.   if MapBits = 0 then
  324.     if IsWorkshopWindow(HWindow) then
  325.       MapBits := LoadBitmapRW(pChar(MapNumber))
  326.     else
  327.       MapBits := LoadBitmap(GetAppInstance, pChar(MapNumber));
  328.   if MapBits = 0 then
  329.     MapBits := LoadBitmap(HInstance, pChar(MapNumber - Get(gww_ID)));
  330.   SetWord(Wrd, MapBits);
  331. end;
  332.  
  333. begin
  334.   BitButtonWinFn := 0;
  335.   case Message of
  336.     wm_Create:
  337.       begin
  338.     { Detect EGA monitor }
  339.     DC := GetDC(0);
  340.     if (GetSystemMetrics(sm_CYScreen) < 480) or
  341.         (GetDeviceCaps(DC, numColors) < 16) then
  342.       BitsNumber := 2000 + Get(gww_ID)
  343.     else
  344.       BitsNumber := 1000 + Get(gww_ID);
  345.     ReleaseDC(0, DC);
  346.  
  347.     { Load bitmaps from resource }
  348.     LoadBits(ofUpBits, BitsNumber);
  349.     LoadBits(ofDownBits, BitsNumber + 2000);
  350.     LoadBits(ofFocUpBits, BitsNumber + 4000);
  351.  
  352.     { Adjust size of button to size of bitmap }
  353.     GetObject(DownBits, SizeOf(Bitmap), @Bitmap);
  354.     GetWindowRect(HWindow, Rect);
  355.     Pt.X := Rect.Left;
  356.     Pt.Y := Rect.Top;
  357.     ScreenToClient(PCreateStruct (lParam)^.hwndParent, Pt);
  358.       MoveWindow(HWindow, Pt.X, Pt.Y,
  359.       Bitmap.bmWidth + bdBorderWidth * 2,
  360.       Bitmap.bmHeight + bdBorderWidth * 2, False);
  361.  
  362.     { Intialize button state }
  363.     with PCreateStruct(lParam)^ do
  364.     begin
  365.       if style and $1F = bs_DefPushButton then
  366.         SetState(bsDefault, True);
  367.       if style and ws_Disabled <> 0 then
  368.         SetState(bsDisabled, True);
  369.     end;
  370.       end;
  371.     wm_NCDestroy:
  372.       begin
  373.     { Destroy all saved bitmaps before the button is destroyed }
  374.     BitButtonWinFn := DefWindowProc(HWindow, Message, wParam, lParam);
  375.     DeleteObject(UpBits);
  376.     DeleteObject(DownBits);
  377.     DeleteObject(FocUpBits);
  378.       end;
  379.     wm_Paint:
  380.       begin
  381.     BeginPaint(HWindow, PS);
  382.     Paint(PS.hDC);
  383.     EndPaint(HWindow, PS);
  384.       end;
  385.     wm_EraseBkGnd:
  386.       begin
  387.     { Squelch the painting of the background to eliminate flicker }
  388.       end;
  389.     wm_Enable:
  390.       SetState(bsDisabled, wParam <> 0);
  391.     wm_SetFocus:
  392.       SetState(bsFocus, True);
  393.     wm_KillFocus:
  394.       SetState(bsFocus or bsKeyDown or bsMouseDown or bsMouseUpDown, False);
  395.     wm_KeyDown:
  396.       if (wParam = $20) and not GetState(bsKeyDown) and
  397.       not GetState(bsMouseDown) then
  398.     SetState(bsKeyDown, True);
  399.     wm_KeyUp:
  400.       if (wParam = $20) and GetState(bsKeyDown) then
  401.         ButtonPressed;
  402.     wm_LButtonDblClk, wm_LButtonDown:
  403.       if InMe(lParam) and not GetState(bsKeyDown) then
  404.       begin
  405.     if GetFocus <> HWindow then SetFocus(HWindow);
  406.     SetState(bsMouseDown, True);
  407.     SetCapture(HWindow);
  408.       end;
  409.     wm_MouseMove:
  410.       if GetState(bsMouseDown) then
  411.     SetState(bsMouseUpDown, not InMe(lParam));
  412.     wm_LButtonUp:
  413.       if GetState(bsMouseDown) then
  414.       begin
  415.     ReleaseCapture;
  416.     if not GetState(bsMouseUpDown) then ButtonPressed
  417.     else SetState(bsMouseDown + bsMouseUpDown, False);
  418.       end;
  419.  
  420.     { *** Handling the rest of these messages are what, at least for
  421.           the dialog manager, makes a push button a push button.  ***}
  422.     wm_GetDlgCode:
  423.       { Sent by the dialog manager to determine the control kind of
  424.     a child window.  Returning dlgc_DefPushButton or
  425.     dlgc_UndefPushButton causes the dialog manager to treat the
  426.     control like a button, sending the bm_SetStyle message to
  427.     move the default button style to the currenly focused button.
  428.  
  429.         The dlgc_Button constant is not documented by Microsoft
  430.         (however, it is documented for OS/2 PM, and appears to work
  431.         the same). If this constant is or'd in, the windows dialog
  432.         manager will take care of all accelerator key processing,
  433.         sending bm_SetState and bm_SetStyle messages when an
  434.         acclerator key is pressed. There is a side effect to using
  435.         the message, however, the dialog manager messes with the word
  436.         at offset 0 from the user Window words. }
  437.  
  438.       if GetState(bsDefault) then
  439.     BitButtonWinFn:= dlgc_DefPushButton or dlgc_Button
  440.       else
  441.     BitButtonWinFn := dlgc_UndefPushButton or dlgc_Button;
  442.     bm_GetState:
  443.       BitButtonWinFn := Integer(GetState(bsKeyDown));
  444.     bm_SetState:
  445.       SetState(bsKeyDown, wParam <> 0);
  446.     bm_SetStyle:
  447.       { Sent by the dialog manager when the button receives or looses
  448.     focus and is not the default button, or when another button
  449.     receives the focus and this button is the default button. }
  450.       SetState(bsDefault, wParam = bs_DefPushButton);
  451.   else
  452.     BitButtonWinFn := DefWindowProc(HWindow, Message, wParam, lParam);
  453.   end;
  454. end;
  455.  
  456. { ==============================================================
  457.   Custom contol interface routines.
  458.   ============================================================== }
  459.  
  460. { BitBtnInfo ---------------------------------------------------
  461.    Return the information about the capabilities of the
  462.    bit button class.
  463.   -------------------------------------------------------------- }
  464. function BitBtnInfo: THandle; export;
  465. var
  466.   hInfo: THandle;
  467.   Info: PRWCtlInfo;
  468. begin
  469.   hInfo := GlobalAlloc(gmem_Share or gmem_ZeroInit,
  470.     SizeOf(TRWCtlInfo));
  471.   if hInfo <> 0 then
  472.   begin
  473.     Info := GlobalLock(hInfo);
  474.     with Info^ do
  475.     begin
  476.       wVersion := $100;         { Version 1.00 }
  477.       wCtlTypes := 2;           { 2 types }
  478.       StrCopy(szClass, 'BitButton');
  479.       StrCopy(szTitle, 'Button');
  480.  
  481.       { Normal (Un-default) push button type }
  482.       with ctType[0] do
  483.       begin
  484.     wWidth := 63 or $8000;
  485.     wHeight := 39 or $8000;
  486.     StrCopy(szDescr, 'Push Button');
  487.     dwStyle := bs_PushButton or ws_TabStop;
  488.     hToolBit := LoadBitmap(HInstance, MakeIntResource(btUndefBits));
  489.     hDropCurs := LoadCursor(HInstance, MakeIntResource(crUndefCurs));
  490.       end;
  491.  
  492.       { Default push button type }
  493.       with ctType[1] do
  494.       begin
  495.     wWidth := 63 or $8000;
  496.     wHeight := 39 or $8000;
  497.     StrCopy(szDescr, 'Default Push Button');
  498.     dwStyle := bs_DefPushButton or ws_TabStop;
  499.     hToolBit := LoadBitmap(HInstance, MakeIntResource(btDefBits));
  500.     hDropCurs := LoadCursor(HInstance, MakeIntResource(crDefCurs));
  501.       end;
  502.     end;
  503.     GlobalUnlock(hInfo);
  504.   end;
  505.   BitBtnInfo := hInfo;
  506. end;
  507.  
  508. type
  509.   PParamRec = ^TParamRec;
  510.   TParamRec = record
  511.     CtlStyle: THandle;
  512.     IdToStr: TIdToStr;
  513.     StrToId: TStrToId;
  514.   end;
  515.  
  516. { BitBtnStyleDlg -----------------------------------------------
  517.     Style dialog's dialog hook.  Used by the dialog and called
  518.     when the control is double-clicked inside the dialog
  519.     editor.
  520.   -------------------------------------------------------------- }
  521. function BitBtnStyleDlg(HWindow: HWnd; Message: Word; wParam: Word;
  522.   lParam: Longint): Longint; export;
  523. const
  524.   Prop = 'Prop';
  525. var
  526.   hRec: THandle;
  527.   Rec: PParamRec;
  528.   Style: PCtlStyle;
  529.   S: array[0..256] of Char;
  530.   Radio: Integer;
  531. begin
  532.   case Message of
  533.     wm_InitDialog:
  534.       begin
  535.     hRec := LoWord(lParam);
  536.     Rec := GlobalLock(hRec);
  537.     Style := GlobalLock(Rec^.CtlStyle);
  538.     SetProp(HWindow, Prop, hRec);
  539.     with Rec^, Style^ do
  540.     begin
  541.       { Set caption }
  542.       SetDlgItemText(HWindow, idCaption, szTitle);
  543.  
  544.       { Set control id }
  545.       IdToStr(wId, S, SizeOf(S));
  546.       SetDlgItemText(HWindow, idControlId, S);
  547.  
  548.       { Set type radio buttons }
  549.       if dwStyle and $F = bs_DefPushButton then
  550.         Radio := idDefaultButton
  551.       else
  552.             Radio := idPushButton;
  553.       CheckRadioButton(HWindow, idDefaultButton, idPushButton,
  554.         Radio);
  555.  
  556.       { Initialize Tab Stop check box }
  557.       CheckDlgButton(HWindow, idTabStop,
  558.         Integer(dwStyle and ws_TabStop <> 0));
  559.  
  560.       { Initialize Disabled check box }
  561.       CheckDlgButton(HWindow, idDisabled,
  562.         Integer(dwStyle and ws_Disabled <> 0));
  563.  
  564.       { Initialize Group check box }
  565.       CheckDlgButton(HWindow, idGroup,
  566.         Integer(dwStyle and ws_Group <> 0));
  567.     end;
  568.     GlobalUnlock(Rec^.CtlStyle);
  569.     GlobalUnlock(hRec);
  570.       end;
  571.     wm_Command:
  572.       case wParam of
  573.     idCancel:
  574.       EndDialog(HWindow, 0);
  575.     idOk:
  576.       begin
  577.         hRec := GetProp(HWindow, Prop);
  578.         Rec := GlobalLock(hRec);
  579.         Style := GlobalLock(Rec^.CtlStyle);
  580.         with Rec^, Style^ do
  581.         begin
  582.           { Get caption }
  583.           GetDlgItemText(HWindow, idCaption, szTitle, SizeOf(szTitle));
  584.  
  585.           { Get control id }
  586.           GetDlgItemText(HWindow, idControlId, S, SizeOf(S));
  587.           wId := StrToId(S);
  588.  
  589.           { Get button type }
  590.           if IsDlgButtonChecked(HWindow, idDefaultButton) <> 0 then
  591.         dwStyle := bs_DefPushButton
  592.           else
  593.                 dwStyle := bs_PushButton;
  594.  
  595.           { Get tab stop }
  596.           if IsDlgButtonChecked(HWindow, idTabStop) <> 0 then
  597.         dwStyle := dwStyle or ws_TabStop;
  598.  
  599.           { Get disabled }
  600.           if IsDlgButtonChecked(HWindow, idDisabled) <> 0 then
  601.         dwStyle := dwStyle or ws_Disabled;
  602.  
  603.           { Get group }
  604.           if IsDlgButtonChecked(HWindow, idGroup) <> 0 then
  605.         dwStyle := dwStyle or ws_Group;
  606.         end;
  607.         GlobalUnlock(Rec^.CtlStyle);
  608.         GlobalUnlock(hRec);
  609.         EndDialog(HWindow, 1);
  610.       end;
  611.       else
  612.     BitBtnStyleDlg := 0;
  613.       end;
  614.     wm_Destroy:
  615.       RemoveProp(HWindow, Prop);
  616.   else
  617.     BitBtnStyleDlg := 0;
  618.   end;
  619. end;
  620.  
  621. { BitBtnStyle --------------------------------------------------
  622.     The function will bring up a dialog box to modify the style
  623.     of the button.  Called when the button is double-clicked in
  624.     the dialog editor.
  625.   -------------------------------------------------------------- }
  626. function BitBtnStyle(hWindow: HWnd; CtlStyle: THandle;
  627.   StrToId: TStrToId; IdToStr: TIdToStr): Bool; export;
  628. var
  629.   hRec: THandle;
  630.   Rec: PParamRec;
  631.   hFocus: HWnd;
  632. begin
  633.   BitBtnStyle := False;
  634.   hRec := GlobalAlloc(gmem_Share, SizeOf(TParamRec));
  635.   if hRec <> 0 then
  636.   begin
  637.     Rec := GlobalLock(hRec);
  638.     Rec^.IdToStr := IdToStr;
  639.     Rec^.StrToId := StrToId;
  640.     Rec^.CtlStyle := CtlStyle;
  641.     GlobalUnlock(hRec);
  642.  
  643.     hFocus := GetFocus;
  644.     BitBtnStyle := Bool(DialogBoxParam(HInstance,
  645.       MakeIntResource(idButtonStyle), HWindow, @BitBtnStyleDlg,
  646.       hRec));
  647.     if hFocus <> 0 then SetFocus(hFocus);
  648.     GlobalFree(hRec);
  649.   end;
  650. end;
  651.  
  652. { BitBtnFlags --------------------------------------------------
  653.     Called to decompose the style double word into the .RC
  654.     script expression that it represents.  This only needs to
  655.     decompose the style bits added to the style double word,
  656.     it need not decompose the, for example, the ws_XXX bits.
  657.     The expression returned must be a valid .RC expression
  658.     (i.e. C syntax, case sensitive).
  659.   -------------------------------------------------------------- }
  660. function BitBtnFlags(Style: LongInt; Buff: PChar;
  661.   BuffLength: Word): Word; export;
  662. begin
  663.   if Style and $F = bs_DefPushButton then
  664.     StrLCopy(Buff, 'BS_DEFPUSHBUTTON', BuffLength)
  665.   else StrLCopy(Buff, 'BS_PUSHBUTTON', BuffLength);
  666. end;
  667.  
  668. { ListClasses --------------------------------------------------
  669.     Called by Resource Workshop retrieve the information
  670.     necessary to edit the custom controls contain in this DLL.
  671.     This is an alternative to the Microsoft xxxStyle convention.
  672.   -------------------------------------------------------------- }
  673. function ListClasses(szAppName: PChar; wVersion: Word;
  674.   fnLoad: TLoad; fnEdit: TEdit): THandle; export;
  675. var
  676.   hClasses: THandle;
  677.   Classes: PCtlClassList;
  678. begin
  679.   LoadResRW := fnLoad;
  680.   hClasses := GlobalAlloc(gmem_Share or gmem_ZeroInit,
  681.     SizeOf(Integer) + SizeOf(TRWCtlClass));
  682.   if hClasses <> 0 then
  683.   begin
  684.     Classes := GlobalLock(hClasses);
  685.     with Classes^ do
  686.     begin
  687.       nClasses := 1;
  688.       with Classes[0] do
  689.       begin
  690.     fnInfo  := BitBtnInfo;
  691.     fnStyle := BitBtnStyle;
  692.     fnFlags := BitBtnFlags;
  693.       end;
  694.     end;
  695.     GlobalUnlock(hClasses);
  696.   end;
  697.   ListClasses := hClasses;
  698. end;
  699.  
  700. exports
  701.   ListClasses,
  702.   BitButtonWinFn;
  703.  
  704. var
  705.   Class: TWndClass;
  706.  
  707. begin
  708.   with Class do
  709.   begin
  710.     lpszClassName := 'BitButton';
  711.     hCursor       := LoadCursor(0, idc_Arrow);
  712.     lpszMenuName  := nil;
  713.     style         := cs_HRedraw or cs_VRedraw or cs_DblClks or cs_GlobalClass;
  714.     lpfnWndProc   := TFarProc(@BitButtonWinFn);
  715.     hInstance     := System.hInstance;
  716.     hIcon         := 0;
  717.     cbWndExtra    := ofSize;
  718.     cbClsExtra    := 0;
  719.     hbrBackground := 0;
  720.   end;
  721.   RegisterClass(Class);
  722. end.
  723.